/*
  Universidade de Sao Paulo - 2014-02
  Programacao Concorrente - Turma 12 Grupo A
  ---
  Bruno Augusto dos Santos - 7696389
  Franco Lamping - 7696351
  Gabriel Massarin de Paula Aguiar - 7573002
*/

#include <iostream>
#include <fstream>
#include <cstdlib>
#include <string>
#include <ctime>

#define INPUT  "in.ppm"
#define OUTPUT "out.ppm"
#define MASK_SIZE 5

/*
* Aplica o filtro da Media nos valores contidos em 'in' e os salvam em 'out'
* in: valores RGB lidos da imagem
* out: valores RGB com a aplicao do filtro
*/
void applyFilter(unsigned char *in,int width,int height,unsigned char *out){
  for(int i = 0; i < height; i++){
    for(int j = 0; j < width; j++){
      int R = 0, G = 0, B = 0;
      for(int k = -MASK_SIZE/2; k <= MASK_SIZE/2; k++){
        for(int l = -MASK_SIZE/2; l <= MASK_SIZE/2; l++){
          if( (i + k >= 0) && (i + k < height) && (j + l >= 0) && (j + l < width) ){
            R += in[(i + k)*width*3 + (j + l) * 3];
            G += in[(i + k)*width*3 + (j + l) * 3 + 1];
            B += in[(i + k)*width*3 + (j + l) * 3 + 2];
          }
        }
      }
      out[i*width*3 + j * 3] 	   = R/(MASK_SIZE*MASK_SIZE);
      out[i*width*3 + j * 3 + 1] = G/(MASK_SIZE*MASK_SIZE);
      out[i*width*3 + j * 3 + 2] = B/(MASK_SIZE*MASK_SIZE);
    }
  }
}

int main(int argc, char **argv){
  unsigned char *in, *out;
  std::string magicNumber;
  int width, height, depth;

  std::ifstream inputFile;
  std::ofstream outputFile;

  /* Leitura dos primeiros valores do cabecalho da imagem
  *  magicNumber: assinatura da imagem
  */
  inputFile.open(INPUT);
  inputFile >> magicNumber >> width >> height >> depth;

  /* Verifica se imagem esta no formato permitido */
  if( magicNumber != "P3" ) {
    std::cout << "Imagem incompativel!" << std::endl;
    return 0;
  }

  /*
  * in: armazena os valores RGB lidos da imagem
  * out: armazena os valores RGB da imagem com o filtro aplicado
  */
  in  = new unsigned char[width*height*3];
  out = new unsigned char[width*height*3];

  /* Le as cores RGB da imagem ppm e as copiam para o vetor 'in' */
  int r,g,b;
  for(int i = 0; i < height; i++){
    for(int j = 0; j < width; j++){
      inputFile >> r >> g >> b;
      in[width * i * 3 + j * 3] = r;
      in[width * i * 3 + j * 3 + 1] = g;
      in[width * i * 3 + j * 3 + 2] = b;
    }
  }
  inputFile.close();

  /* Registra o inicio do processamento */
  clock_t t;
  t = clock();

  /* Aplica o filtro */
  applyFilter(in,width,height,out);

  /* Registra o fim do processamento */
  t = clock()-t;
  std::cout << "Elapsed " << t << " clicks (" << ((float)t)/CLOCKS_PER_SEC << " seconds)." << std::endl;

  /*
  * Imprime os valores contidos em 'out' no arquivo de saida,
  * gerando a imagem final com o filtro da Media aplicado
  */
  outputFile.open(OUTPUT);
  outputFile << "P3" << std::endl << width << " " << height << std::endl << depth << std::endl;
  for(int i = 0; i < height; i++){
    for(int j = 0; j < width; j++){
      outputFile << static_cast<unsigned>(out[width * i * 3 + j * 3])     << " ";
      outputFile << static_cast<unsigned>(out[width * i * 3 + j * 3 + 1]) << " ";
      outputFile << static_cast<unsigned>(out[width * i * 3 + j * 3 + 2]) << " ";
    }
    outputFile << std::endl;
  }
  outputFile.close();

  delete[] in;
  delete[] out;

  return 0;

}
